<?php

class Set implements XMLConvertable, JSONConvertable {

    protected $elements;
    protected $typifed;
    protected $index;
    protected $name;

    function __construct($init = null, $typifed = false) {
        $this->elements = $init;
        reset($this->elements);
        $this->typifed = $typifed;
        $this->index = 0;
    }

    /**
     * Возвращает массив хранимых значений
     * @return array
     */
    function read_array() {
        return $this->elements;
    }

    function __get($name) {
        if ($this->typifed && !key_exists($name, $this->elements)) throw new Exception("Field `$name` not defined!");
        return @$this->elements[$name];
    }

    function __set($name, $val) {
        if ($this->typifed && !key_exists($name, $this->elements)) throw "Field `$name` not defined!";
        $this->elements[$name] = $val;
    }

    /**
     * использует пользовательскую функцию для обхода элементов набора
     * @param strind $f имя функции
     */
    function iterate($f) {
        foreach ($this->elements as $k=>$v) {
            $f($k, $v);
        }
    }

    /**
     * возвращает следующий элемент списка
     *
     * @return mixed
     */
    function next() {
        return next($this->elements);
    }

    /**
     * возвращает предыдущий элемент набора
     * @return mixed
     */
    function prev() {
        return prev($this->elements);
    }
    /**
     * возвращает текущий элемент и сдвигает указатель на следующий элемент
     * @return mixed
     */
    function curn () {
        $ret = $this->current();
        $this->next();
        return $ret;
    }

    /**
     * Возвращает текущий элемент набора
     * @return mixed
     */
    function current() {
        return current($this->elements);
    }

    /**
     * Возвращает ключ текущего элемента набора
     * @return mixed ключ текущего элемента набора
     */
    function key() {
        return key($this->elements);
    }

    /**
     * Сбрасывает указатель на первый элемент набора
     */
    function reset() {
        reset($this->elements);
    }

    /**
     * Возвращает количество элементов в наборе
     * @return integer
     */
    function count() {
        return count($this->elements);
    }

    /**
     * Возвращает значения набора в виде объекта SimpleXMLElement
     * @param SimpleXMLElement $parent
     * @return SimpleXMLElement
     */
    function toXML(SimpleXMLElement &$parent = NULL) {
        if (!$parent) $xml = simplexml_load_string('<set/>');
        else {
            $xml = $parent->addChild('set');
        }
        foreach ($this->elements as $key=>$elem) {
            if (is_a($elem, 'XMLConvertable')) {
                $elem->toXML($xml);
            } elseif (is_string($key)) {
                $xml->$key = $elem.'';
            } else {
                $xml->element[$key] =  $elem;
                $xml->element[$key]['id'] = $key;
            }
        }
        return $xml;
    }

    /**
     * Возвращает старое и (если передано) устанавливает новое имя набора
     * @param string $nn новое имя набора
     * @return string
     */
    function name($nn = NULL) {
        $ret = $this->name;
        if ($nn != NULL) $this->name = $nn;
        return $ret;
    }

    /**
     * преобразует набор в json-строку
     * @return string
     */
    function toJSON() {
        $res = json_encode($this->elements);
        return $res;
    }
}
?>